// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "VideoEngine.h"
#include "RemoteVideoEncoder.h"

/*
 * @功能描述：构造函数
*/
VideoEngine::VideoEngine()
{
}

/*
 * @功能描述：析构函数
*/
VideoEngine::~VideoEngine()
{
}

uint32_t VideoEngine::SetOpt(const std::string &key, const std::string value)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_INIT_FAIL;
    }
    remoteVideoEncoder->SetOpt(key,value);
    INFO("SetOpt success...........");
    return VMI_SUCCESS;
}


/*
 * @功能描述：初始化编码引擎
 * @参数 [in] encodeType：编码方式cpu
 * @参数 [in] param:编码参数结构体
 * @返回值： 0 成功
 *          VMI_VIDEO_ENGINE_INIT_FAIL 初始化失败，
 *          VMI_VIDEO_ENGINE_PARAM_INVALID 无效参数
*/
uint32_t VideoEngine::InitEncoder(VideoEncoderParam &param)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_INIT_FAIL;
    }
    if (remoteVideoEncoder->GetStatus() == VMI_ENCODE_ENGINE_INVALID) {
        if (remoteVideoEncoder->InitEncoder(param) < 0) {
            ERR("Init encoder fail.");
            return VMI_VIDEO_ENGINE_INIT_FAIL;
        }
        INFO("Init done.");
        return VMI_SUCCESS;
    }
    ERR("VideoEngine status is not VMI_ENCODE_ENGINE_INVALID");
    return VMI_VIDEO_ENGINE_INIT_FAIL;
}

/*
 * @功能描述：开启编码引擎
 * @返回值： 0 成功，
 *          VMI_VIDEO_ENGINE_START_ERR 启动失败
*/
uint32_t VideoEngine::StartEncoder()
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_START_ERR;
    }
    if (this->m_videoCallback == nullptr){
        ERR("VideoCallback not regist");
        return VMI_VIDEO_ENGINE_START_ERR;
    }
    if (remoteVideoEncoder->StartEncoder() < 0) {
        ERR("Init encoder fail.");
        return VMI_VIDEO_ENGINE_START_ERR;
    }
    INFO("VideoEngine start success.");
    return VMI_SUCCESS;
}

/*
 * @功能描述：编码引擎状态获取
 * @参数 [out] stat：编码引擎状态
 * @返回值：VMI_SUCCESS 成功
*/
uint32_t VideoEngine::GetEncoderStatus(EngineStat &stat)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_GET_STAT_ERR;
    }
    stat = remoteVideoEncoder->GetStatus();
    return VMI_SUCCESS;
}

/*
 * @功能描述：编码引擎统计信息获取
 * @参数 [out] statics：编码引擎统计信息
 * @返回值：VMI_SUCCESS 成功
*/
uint32_t VideoEngine::GetEncoderStatistics(EncoderStatistics &statics)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_GET_STAT_ERR;
    }
    statics = remoteVideoEncoder->GetStatics();
    return VMI_SUCCESS;
}

/*
 * @功能描述：设置引擎编码参数
 * @参数 [in] statics：编码引擎设置参数结构体
 * @返回值：VMI_SUCCESS 成功
 *         VMI_VIDEO_ENGINE_CONFIG_ERR 设置错误
*/
uint32_t VideoEngine::SetEncoderParam(VideoEncoderParam &param)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_CONFIG_ERR;
    }
    if (remoteVideoEncoder->SetParam(param) < 0) {
        ERR("SetParam value is invalid..use default param");
        return VMI_VIDEO_ENGINE_CONFIG_ERR;
    }
    return VMI_SUCCESS;
}

/*
 * @功能描述：编码引擎编码一帧数据接口
 * @参数 [in] src：待编码数据地址
 * @参数 [in] length：待编码数据长度
 * @返回值：VMI_SUCCESS 成功
 *          VMI_VIDEO_ENGINE_ENCODE_ERR 编码一帧错误
 *          VMI_VIDEO_ENGINE_ERR 编码引擎错误
*/
uint32_t VideoEngine::EncodeOneFrame(uint8_t *src, uint32_t length)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    remoteVideoEncoder->ResetEncoder();

    VideoParamExt outEncodeParam = {0, 0, 0, 0};
    std::pair<uint8_t *, uint32_t> outData;

    if (remoteVideoEncoder->EncodeOneFrame(src, length, outData, outEncodeParam, false) < 0) {
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    (void)this->m_videoCallback(outData.first, outData.second, outEncodeParam);
    return VMI_SUCCESS;
}

bool del(uint8_t *p) {
    delete[] p;
}

/*
 * @功能描述：编码引擎编码一帧数据接口
 * @参数 [in] src：待编码数据地址
 * @参数 [in] length：待编码数据长度
 * @返回值：VMI_SUCCESS 成功
 *          VMI_VIDEO_ENGINE_ENCODE_ERR 编码一帧错误
 *          VMI_VIDEO_ENGINE_ERR 编码引擎错误
*/
uint32_t VideoEngine::EncodeOneFrame(uint8_t *src, uint32_t length, VideoParamExt& param)//lint !e1072
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    std::pair<uint8_t *, uint32_t> outData{nullptr, 0};
    remoteVideoEncoder->ResetEncoder();
    if (remoteVideoEncoder->EncodeOneFrame(src, length, outData, param, false) < 0) {
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    if (m_firstFrame && outData.second == 0) {
        m_firstFrame = false;
        int encodeFirstFrameTime = 0;
        while (encodeFirstFrameTime < 5) {
            if (remoteVideoEncoder->EncodeOneFrame(src, length, outData, param, false) < 0) {
                return VMI_VIDEO_ENGINE_ENCODE_ERR;
            }
            if (outData.second != 0) {
                break;
            }
            encodeFirstFrameTime++;

            if (encodeFirstFrameTime == 5) {
                ERR("Failed to repeated encode first frame.");
                return VMI_VIDEO_ENGINE_ENCODE_ERR;
            }
        }
        INFO("Repeated encode first frame, encodeFirstFrameTime is %d.", encodeFirstFrameTime);
    }
    (void)this->m_videoCallback(outData.first, outData.second, param);
    return VMI_SUCCESS;
}

unsigned int VideoEngine::getCurrentFPS(uint64_t &currentTs) 
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return 0;
    }

    return remoteVideoEncoder->getCurrentFPS(currentTs);
}

uint32_t VideoEngine::EncodeRepeatOneFrame(uint8_t *src, uint32_t length, VideoParamExt& repeatParam)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    std::pair<uint8_t *, uint32_t> outData{nullptr, 0};
    remoteVideoEncoder->ResetEncoder();
    if (remoteVideoEncoder->EncodeOneFrame(src, length, outData, repeatParam, true) < 0) {
        return VMI_VIDEO_ENGINE_ENCODE_ERR;
    }
    (void)this->m_videoCallback(outData.first, outData.second, repeatParam);
    return VMI_SUCCESS;
}

/*
 * @功能描述：注册编码引擎发送数据回调函数
 * @参数 [in] callback：数据发送函数指针
 * @返回值：VMI_SUCCESS 成功
 *       VMI_VIDEO_ENGINE_REGISTER_ERR 注册函数错误
*/
uint32_t VideoEngine::RegisterEncoderCallback(VIDEOCALLBACK callback)
{
    if (callback == nullptr) {
        ERR("The Encodercallback is nullptr");
        return VMI_VIDEO_ENGINE_REGISTER_ERR;
    }
    this->m_videoCallback = callback;
    return VMI_SUCCESS;
}

/*
 * @功能描述：注册编码引擎日志回调函数
 * @参数 [in] logCallback：日志处理函数指针
 * @返回值：VMI_SUCCESS 成功
 *        VMI_VIDEO_ENGINE_REGISTER_ERR 注册函数错误
*/
uint32_t VideoEngine::RegisterLogCallback(LOGCALLBACK logCallback)
{
    if (logCallback == nullptr) {
        ERR("The logCallback is nullptr");
        return VMI_VIDEO_ENGINE_REGISTER_ERR;
    }
    SetLogCallback(logCallback);
    return VMI_SUCCESS;
}

/*
 * @功能描述：停止编码引擎
 * @返回值：VMI_SUCCES 成功
 *          VMI_VIDEO_ENGINE_STOP_ERR 停止操作失败
*/
uint32_t VideoEngine::StopEncoder()
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_STOP_ERR;
    }
    if (remoteVideoEncoder->StopEncoder() < 0) {
        ERR("Failed stop VideoEngine");
        return VMI_VIDEO_ENGINE_STOP_ERR;
    }
    return VMI_SUCCESS;
}

/*
 * @功能描述：销毁编码引擎
 * @返回值：VMI_SUCCESS 成功
 *          VMI_VIDEO_ENGINE_DESTROY_ERR 销毁编码引擎失败
 */
uint32_t VideoEngine::DestroyEncoder()
{
    if (RemoteVideoEncoder::DestroyInstance() < 0) {
        ERR("VideoEngine DestroyEncoder fail...");
        return VMI_VIDEO_ENGINE_DESTROY_ERR;
    }
    return VMI_SUCCESS;
}
/*
 *
 */
uint32_t VideoEngine::SetEncoderKeyFrame()
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return VMI_VIDEO_ENGINE_PARAM_UNSUPORTED;
    }
    remoteVideoEncoder->m_keyFrameFlag = true;
    return VMI_SUCCESS;
}

uint32_t VideoEngine::GetEncoderResetFlag(bool &resetFlag)
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return -1;
    }
    resetFlag = remoteVideoEncoder->GetResetFlag();
    INFO("get resetFlag success : %d", resetFlag);
    return 0;
}

void VideoEngine::reloadConfig()
{
    RemoteVideoEncoder *remoteVideoEncoder = RemoteVideoEncoder::GetInstance();
    if (remoteVideoEncoder == nullptr) {
        ERR("Failed to instantiate.");
        return;
    }

    remoteVideoEncoder->reloadConfig();
}